/*
 * Properties.cpp
 *
 *  Created on: Mar 24, 2011
 *      Author: kimi
 */

#include "Properties.h"

using namespace std;

Properties::Properties(string filePath) {
	this->filePath = filePath;
	this->loaded = false;
	this->properties = NULL;
	this->propNum = 0;
	this->dirty = true;
}

void Properties::reload(void) {
	// number of entries in file
	int nEntries = 0;
	bool hasError = false;

	// read entries from file and dump into memory
	ifstream propsFile;

	propsFile.open(this->filePath.c_str());

	this->loaded = true;
	int capacity = 24;

	this->properties = new Property[capacity]; //custom size;

	if (propsFile.is_open()) {

		string aLine;
		while (getline(propsFile, aLine)) {

			Property aProperty = Property(aLine);

			if (aProperty.isInvalid()) {
				hasError = true;
				break;
			}

			this->properties[nEntries] = aProperty;

			if (nEntries + 1 >= capacity) {
				// increase array size
				Property *temp = new Property[capacity * 2];

				for (int i = 0; i < nEntries; i++)
					temp[i] = this->properties[i];

				capacity *= 2;

				delete[] this->properties;

				this->properties = temp;
			}

			nEntries++;
		}
	}

	this->propNum = nEntries;

	propsFile.close();

	if (hasError == true) {
		this->loaded = false;
		cerr << "Error" << endl;
	}

}

/*
Properties::~Properties() {

}
*/
bool Properties::load() {
	reload();

	if (this->loaded == false) {
//		cout << "properties loaded: NO"<<endl;
	}
	else {
//		cout << "properties loaded: YES"<<endl;
	}



	return loaded;
}

bool Properties::save() {
	// dump memory to file
	ofstream outfile(this->filePath.c_str(), ios_base::out | ios_base::trunc);

	for (int i = 0; i < propNum; i++) {
		if (properties[i].isInvalid() == false)
			outfile << properties[i].toString() << endl;
	}

	outfile.close();

	dirty = true;
	return true;
}

string Properties::remove(string key) {
	string value;

	if (dirty) {
		dirty = false;
		reload();
	}

	if (loaded != false) {
		// find property
		for (int i = 0; i <= propNum; i++) {
			if (key == properties[i].getKey()) {
				value = properties[i].getValue();
				properties[i].invalidate();
			}
		}
	}

	return value;
}

string Properties::get(string key) {
	string value;

	if (dirty) {
		dirty = false;
		reload();
	}

	if (loaded != false) {
		// find property
		for (int i = 0; i <= propNum; i++) {
			if (key == properties[i].getKey()) {
				value = properties[i].getValue();
				break;
			}
		}
	}

	stringstream trimmer;
	trimmer << value;
	value.clear();
	trimmer >> value;

	return value;
}

bool Properties::put(string key, string value) {
	// see if exist....
	bool exists = false;

	if (dirty) {
		dirty = false;
	//	cout << "Reloading" << endl;
		reload();
	}

	//cout << "Loaded " << loaded << endl;
	if (loaded == true) {

		for (int i = 0; i <= propNum; i++) {
			if (key == properties[i].getKey()) {
				properties[i].setValue(value);
				exists = true;
				break;
			}
		}

		if (exists == false) {
			// resize if necessary
			int capacity = sizeof(this->properties);
			if (this->propNum + 1 >= capacity) {
				// increase array size
				Property *temp = new Property[capacity * 2];

				for (int i = 0; i < this->propNum; i++)
					temp[i] = this->properties[i];

				capacity *= 2;

				delete[] this->properties;

				this->properties = temp;
			}

			Property aProp = Property(key, value);

			this->properties[this->propNum] = aProp;
			this->propNum++;
		}
	}

	return exists;
}

unsigned int Properties::getInt(string key) {
	string value = get(key);
	StringUtils *su = new StringUtils();

	unsigned int uiValue = -1;

	uiValue = su->toInt(value);

	delete su;
	return uiValue;
}

bool Properties::putInt(string key, unsigned int value) {
	StringUtils *su = new StringUtils();
	string val = su->toString(value);
	bool exists = put(key,val);
	delete su;
	return exists;
}


